package com.navinfo.tripanalysis.common.arithmetic;

import com.navinfo.tripanalysis.common.arithmetic.manager.AbstractArithmetic;
import com.navinfo.tripanalysis.common.util.ArithmeticUtils;
import com.navinfo.tripanalysis.common.arithmetic.common.OuterEventData;
import com.navinfo.tripanalysis.common.arithmetic.common.OuterStatisticData;
import com.navinfo.tripanalysis.common.arithmetic.convert.EventDataConvert;
import com.navinfo.tripanalysis.common.arithmetic.custom.VarSharpDeceleration;
import com.navinfo.tripanalysis.common.arithmetic.enums.EventStatus;
import com.navinfo.tripanalysis.common.config.ConfigMap;
import com.navinfo.tripanalysis.common.protocol.java.EventDataPb;

import java.util.Optional;

/**
 * 急减速算法<br/>
 * 依赖{@link Mileage}里程油耗算法<br/>
 * 输出：统计、事件<br/>
 * @author 沈东生
 */
public class SharpDeceleration extends AbstractArithmetic<VarSharpDeceleration> {
    /**
     * 事件类型
     */
    private static final EventDataPb.EventType event = EventDataPb.EventType.sharpDeceleration;
    /**
     * 时长阀值 单位：ms
     */
    private int timeThreshold = ConfigMap.getInteger("H_Dec_Time_Threshold");
    /**
     * 加速度阀值，单位m/s2
     */
    private Double acceleratedSpeedThreshold = ConfigMap.getDouble("H_Dec_Threshold");


    /**
     * 判断当前是否为急减速
     */
    boolean isCurSharpDeceleration() {
        return (drivingData!=null && drivingData.getCommonData().getBrake()==0x01 && drivingData.getCommonData().getAcceleratedSpeed()<acceleratedSpeedThreshold);
    }

    @Override
    public void calculate() {
        logger.debug("进入急减速算法.[terminalId:{}]", terminalId);
        VarSharpDeceleration var = super.getObj();

        boolean preSharpDeceleration = var.isPreSharpDeceleration();
        boolean curSharpDeceleration = isCurSharpDeceleration();
        logger.debug("急减速算法，急减速状态：preSharpDeceleration:{},curSharpDeceleration:{}.[terminalId:{}]", preSharpDeceleration, curSharpDeceleration, terminalId);

        //算法计算
        EventStatus eventStatus = super.getEventStatus(preSharpDeceleration, curSharpDeceleration);
        switch (eventStatus) {
            case START:
                logger.debug("急减速算法，事件开始.[terminalId:{}]", terminalId);
                startEventData(event);
                break;
            case IN:
                logger.debug("急减速算法，事件中.[terminalId:{}]", terminalId);
                calcEventData(event);
                break;
            case END:
                logger.debug("急减速算法，事件结束.[terminalId:{}]", terminalId);
                calcEventData(event);
                endEventData();
                break;
            default:
                logger.debug("急减速算法，急减速状态：上一次和本次都未急减速，跳出算法.[terminalId:{}]", terminalId);
        }


        //行程结束时要清理对应的未结束事件
        if (getCommonData().isTripLastNode()) {
            endEventData();
        }

        //设置上一个点状态、供下个点计算
        var.setPreSharpDeceleration(curSharpDeceleration);
        logger.debug("急减速算法结束.[terminalId:{}]", terminalId);
    }

    @Override
    public void collect(OuterStatisticData statisticDataOut) {
        VarSharpDeceleration var = getObj();
        statisticDataOut.setSharpDownSpeedNumber(var.getNumber());
        statisticDataOut.setSharpDownSpeedMileage(ArithmeticUtils.mileageMToM(var.getMileage()));
        statisticDataOut.setSharpDownSpeedDuration(ArithmeticUtils.timeMsToSecond(var.getDuration()));
    }

    /**
     * 处理事件的结束状态
     */
    private void endEventData() {
        Optional.ofNullable(drivingData.getEventData(event)).ifPresent(eventData -> {
            EventDataConvert.convertEnd(eventData, drivingData);
            drivingData.removeEventData(event);

            if (Optional.ofNullable(eventData.getDuration()).orElse(0L) >= timeThreshold) {
                logger.debug("急减速时间{}ms,进行统计", Optional.ofNullable(eventData.getDuration()).orElse(0L));

                //事件结束，统计里程、油耗、时长、次数加1
                eventDataToVar(eventData);

                //放入输出事件列表
                drivingData.addEventDataToList(eventData);
            } else {
                logger.debug("急减速时间{}ms,小于阈值{}ms，不进行统计", Optional.ofNullable(eventData.getDuration()).orElse(0L), timeThreshold);
            }
        });
    }

    /**
     * 事件数据赋值到统计数据中
     * @param eventData
     */
    private void eventDataToVar(OuterEventData eventData){
        VarSharpDeceleration var = super.getObj();
        var.setNumber(var.getNumber()+1);
        var.addMileage(Optional.ofNullable(eventData.getExtendField05()).orElse(0.0));
        var.addDuration(Optional.ofNullable(eventData.getDuration()).orElse(0L).intValue());
    }
}
